// interpreter code used "Linked List Interpreter using Function Pointers"
// in Developing Embedded Software in C by Prof. Valvano

#include "OS.h"
#include "ADCT0ATrigger.h"
#include "PLL.h"
#include "ST7735.h"
#include "UART2.h"

int GlbCnt = 0;  // reserved for later
long data[40];   // reserved for later

void DisableInterrupts(void); // Disable interrupts
void EnableInterrupts(void);  // Enable interrupts
void WaitForInterrupt(void);  // low power mode

// used to initialize PD0 for measurements
#define GPIO_PORTD_DIR_R        (*((volatile unsigned long *)0x40007400))
#define GPIO_PORTD_AFSEL_R      (*((volatile unsigned long *)0x40007420))
#define GPIO_PORTD_DEN_R        (*((volatile unsigned long *)0x4000751C))
#define GPIO_PORTD_AMSEL_R      (*((volatile unsigned long *)0x40007528))
#define GPIO_PORTD_PCTL_R       (*((volatile unsigned long *)0x4000752C))
#define SYSCTL_RCGC2_R          (*((volatile unsigned long *)0x400FE108))
#define SYSCTL_RCGC2_GPIOD      0x00000008  // port D Clock Gating Control
#define PD0                    (*((volatile unsigned long *)0x40007004))
// used to initialize PD0 for measurements

// used in OS_AddPeriodicThread
void Display(void){
	//int Section = GlbCnt % 2;
	//int Value = ADCvalue;
	//ST7735_Message(Section, 1, "current value =", Value);
	//GlbCnt++;
}
// used in OS_AddPeriodicThread

// for interpreter
const struct Node{            // build nodes, similar to TCB?
	unsigned char Letter;
	void (*fnctPt)(void);
	const struct Node *Next;
};

typedef const struct Node NodeType;
typedef NodeType * NodePtr;

//void CommandA(void){
//	int value;
//	value = ADCvalue;
//	ST7735_FillRect(0, 60, 128, 80, ST7735_Color565(255, 255, 255));
//	ST7735_Message(0, 3, "ADC Value1 =", value);
//}

void CommandB(void){
	int value;
	value = ADCvalue;
	ST7735_FillRect(0, 120, 128, 140, ST7735_Color565(0, 0, 0));
	ST7735_Message(1, 2, "ADC Value2 =", value);
}

void CommandC(void){
	int value;
	value = ADCvalue;
	ST7735_FillRect(0, 140, 128, 160, ST7735_Color565(0, 0, 0));
	ST7735_Message(1, 3, "ADC Value3 =", value);
}

NodeType LL[2]={                // command list, can be modified
//  { 'a', &CommandA, &LL[1]},
  { 'b', &CommandB, &LL[1]},
  { 'c', &CommandC, 0 }
};
// for interpreter

int main(void){
	char string[20];     // input string from terminal
	NodePtr Pt;          // used in interpreter
	volatile unsigned long delay;
	
	PLL_Init();          // system runs at 50MHz
	UART_Init();         // initialize UART0, PA0 = U1Rx, PA1 = U1Tx

	// initialize PD0
	SYSCTL_RCGC2_R |= SYSCTL_RCGC2_GPIOD; // activate port D
  delay = SYSCTL_RCGC2_R;      // allow time for clock to stabilize
  GPIO_PORTD_DIR_R |= 0x01;    // make PD0 out
  GPIO_PORTD_AFSEL_R &= ~0x01; // regular port function 
  GPIO_PORTD_DEN_R |= 0x01;    // enable digital I/O on PD0
                               // configure PD0 as GPIO
  GPIO_PORTD_PCTL_R = (GPIO_PORTD_PCTL_R&0xFFFF0000)+0x00000000;
  GPIO_PORTD_AMSEL_R &= ~0x01; // disable analog functionality on PD0
	// initialize PD0
	
// give some initial output on the screen
	ST7735_InitR(INITR_REDTAB);
  ST7735_FillScreen(ST7735_Color565(255, 0, 255));
  //SysTick_Wait1ms(100);
	
  ST7735_FillRect(0, 0, 128, 80, ST7735_Color565(255, 255, 255));
  ST7735_FillRect(0, 80, 128, 160, ST7735_Color565(0, 0, 0));
	
	ST7735_Message(0, 0, "TstStr", 1234);
	ST7735_Message(0, 1, "UT ECE", 4321);
	ST7735_Message(0, 2, "SysTest", 1234);
	ST7735_Message(0, 3, "TstStr2", 4321);
	//SysTick_Wait1ms(500);
	
	ST7735_Message(1, 0, "EE380L", 1234);
	ST7735_Message(1, 1, "TstStr", 4321);
	ST7735_Message(1, 2, "Real T", 1234);
	//ST7735_Message(1, 3, "Value (mV) =", 4321);
	//SysTick_Wait1ms(1000);
// give some initial output on the screen
  
	// test ADC_Collect when uncommented
	// ADC_Collect(0, 50, buffer, 16);  
	// while(1){};  // modified
	// test ADC_Collect when uncommented
		
	OS_AddPeriodicThread(&Display, 100, 2);       // add thread Display, period = 20ns*100 = 2000ns, priority = 2
	                                              // Display is outputing current ADCvalue on both sections on the LCD
	ADC0_InitTimer0ATriggerSeq3(0, 76, 64934);    // ADC channel 0, 10 Hz sampling
	                                              // sampling rate = 50MHz / 77 / 64935 = 10Hz
  EnableInterrupts();
	
  while(1){
    WaitForInterrupt();
		// test UART
		UART_OutString("InString: ");
    UART_InString(string,19);
    UART_OutString(" OutString="); 
		UART_OutString(string); 
		OutCRLF();
		ST7735_FillRect(0, 140, 128, 160, ST7735_Color565(0, 0, 0));
		ST7735_Message(1, 3, string, 4321);
		// test UART
		
		// interpreter
	  Pt=&LL[0];         // first node to check
		while(Pt){
      if(string[0]==Pt->Letter){
        Pt->fnctPt();  // execute function
        break;}        // leave while loop
      else{
        Pt=Pt->Next;   // go to check next function
        if(Pt==0) UART_OutString(" Error"); OutCRLF();
			}
		}
		// interpreter
    }

}
